"""
Copyright 2012 Wieser Dietmar, Margit Mutschlechner.

This file is part of Multimedia Social Networking Platform.

Multimedia Social Networking Platform is free software: 
you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Multimedia Social Networking Platform is distributed
in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Multimedia Social Networking Platform.  
If not, see <http://www.gnu.org/licenses/>.

"""

from threading import Timer
from msnp.logger import Logger
from msnp.service.network import logic

#the timer queue
__rtTimerQueue = []

def disableRTTimerEntry(rtMessage):
    """This function sets the relevant flag of the queue entry that corresponds to the given rtMessage to false.
    
    The call is forwarded to the __changeQueue function.
    
    Args:
        rtMessage: the ReliableTransportMessage instance
    """
    
    __changeQueue(rtMessage)
            
            
def deleteRTTimerEntry(rtMessage):
    """This function removes the queue entry that corresponds to the given rtMessage.
    
    The call is forwarded to the __changeQueue function.
    
    Args:
        rtMessage: the ReliableTransportMessage instance
    """
    
    __changeQueue(rtMessage, True)
            
            
def __changeQueue(rtMessage, delete=False):
    """This function changes the queue entry that corresponds to the given rtMessage.
    
    It either removes the entry (delete=True) or sets the relevant flag to false (delete=False).
    
    Args:
        rtMessage: the ReliableTransportMessage instance
        delete: boolean determining whether the entry has to be removed or disabled.
    """
    
    global __rtTimerQueue
    for entry in __rtTimerQueue:
        if entry.getRtMessage().isEqual(rtMessage):
            if delete:
                __rtTimerQueue.remove(entry)
            else:
                entry.setRelevant(False)
                
                
def addAndStartRTTimerEntry(rtMessage):
    """This function adds a new entry to the queue and starts its timer.
    
    Args:
        rtMessage: the ReliableTransportMessage instance
    """
    
    global __rtTimerQueue
    aEntry = RTTimerQueueEntry(rtMessage)
    __rtTimerQueue.append(aEntry)
    aEntry.startTimer()
    
    
class RTTimerQueueEntry():
    """Class for the entries of the reliable transport queue.

    Attributes:
        __timerInterval: the timer interval (float - 15 seconds standard)
        __rtMessage: the corresponding ReliableTransportMessage instance
        __timer: the Timer instance
        __relevant: boolean determining whether the current queue entry is still relevant.
    """
    
    def __init__(self, rtMessage):
        self.__timerInterval = 15.0
        self.__rtMessage = rtMessage
        self.__timer = None
        self.__relevant = True
        
    def startTimer(self):
        """This method starts the timer."""
        
        self.__timer = Timer(self.__timerInterval, self.__timeOut)
        self.__timer.start()
        
        
    def setRelevant(self, isRelevant):
        """This method changes the relevant flag."""
        
        self.__relevant = isRelevant
        
        
    def getRtMessage(self):
        """This method returns the rtMessage."""
        
        return self.__rtMessage
    
    
    def __timeOut(self):
        """This function is called when the timer runs out.
        
        If the relevant flag is still True, the sequential delivery was not successful.
        Therefore an error function is called to broadcast the message.
        Otherwise the entry is removed from the queue."""
        
        if self.__relevant:
            logic.CrashLogic.executeRTMessageErrorCallback(self.__rtMessage)
        else:
            Logger.info("RTTimer -> message " + self.__rtMessage.getType() + " no more relevant")
        deleteRTTimerEntry(self.__rtMessage)

